    /*
        队列数据管理：
            定义队列数据描述类
                1，队列名称
                2，是否持久化标志
                3，是否独占标志
                4，是否自动删除标志
            持久化功能实现类
                1，创建/删除 队列数据表
                2，新增一个队列到数据库中
                3，删除一个队列从数据库 中
                4，查询所有队列数据
            队列管理类的实现（向 外提供的）
                1，声明一个队列 ，有则OK，无则创建
                2，删除队列
                3，获取指定队列
                4，获取所有队列——将数据从磁盘恢复到内存中
                5，判断指定队列是否存在
                6，获取队列数量
    */
#ifndef __M_QUEUE_H__
#define __M_QUEUE_H__
#include "google/protobuf/map.h"
#include "../mqcommon/helpper.hpp"
#include "../mqcommon/logger.hpp"
#include "../mqcommon/mq_message.pb.h" //这里包含交换机类型，持久化等枚举类型
#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include <mutex>

namespace xgmq
{
    // 定义队列描述类
    struct MsgQueue
    {
        using ptr = std::shared_ptr<MsgQueue>;
        std::string name;                                  // 队列名称
        bool durable;                                      // 是否持久化
        bool exclusive;                                    // 是否独占标志
        bool auto_delete;                                  // 是否自动删除标志
        google::protobuf::Map<std::string,std::string> args; // 其他参数

        MsgQueue() {}
        MsgQueue(const std::string &qname,
                 bool qdurable,
                 bool qexclusive,
                 bool qauto_delete,
                 const google::protobuf::Map<std::string,std::string>& qargs)
            : name(qname), durable(qdurable), exclusive(qexclusive), auto_delete(qauto_delete), args(qargs) {}

        // 实现将args序列化和反序列化的接口
        // 格式为k1=v11&&k2=v2&...
        void setArgs(const std::string &str_args)
        {
            // 将args转化为键值对的形式存储在map中
            std::vector<std::string> result;
            StrSplit::split(str_args, "&", result); // 按照&分割开，放入result数组中

            for (auto &str : result)
            {
                auto pos = str.find("=");
                std::string key = str.substr(0, pos);
                std::string val = str.substr(pos + 1);
                args[key]=val;
            }
        }
        std::string getArgs()
        {
            std::string result;
            for (auto start = args.begin(); start != args.end(); start++)
            {
                result += start->first + "=" + start->second + "&";
            }
            return result;
        }
    };

    using MsgQueueMap = std::unordered_map<std::string, MsgQueue::ptr>;
    // 实现队列持久化类
    class MsgQueueMapper
    {
    public:
        MsgQueueMapper(const std::string &dbfile) : _sql_help(dbfile)
        {
            // 针对传入的dbfile，判断是其路径是否存在
            FileHelper file_help(dbfile);
            std::string path = file_help.parentDirector(dbfile);
            if (file_help.isExits() == false)
            {
                file_help.createDirector(path);
            }
            // 创建/打开数据库
            assert(_sql_help.open());

            createTable();
        }
        void createTable()
        {
            // create table if not exists queue_table(name varchar(32),durable,exclusive,auto_delete,args);
            std::stringstream ss;
            ss << "create table if not exists queue_table(";
            ss << "name varchar(32),";
            ss << "durable int,";
            ss << "exclusive int,";
            ss << "auto_delete int,";
            ss << "args varchar(128));";

            assert(_sql_help.exec(ss.str(), nullptr, nullptr));
        }
        void removeTable()
        {
            // drop table if exists queue_table;
            std::string sql = "drop table if exists queue_table";
            _sql_help.exec(sql, nullptr, nullptr);
        }
        // 新增一个队列
        bool insert(MsgQueue::ptr &queue)
        {
            // insert into queue_table values(name,durable,exclusive,auto_delete,args);
            std::stringstream ss;
            ss << "insert into queue_table values(";
            ss << "'" << queue->name << "',";
            ss << queue->durable << ",";
            ss << queue->exclusive << ",";
            ss << queue->auto_delete << ",";
            ss << "'" << queue->getArgs() << "');";
            return _sql_help.exec(ss.str(), nullptr, nullptr);
        }
        // 删除一个队列
        void remove(const std::string &name)
        {
            // delete from queue_table where name=
            std::stringstream ss;
            ss << "delete from queue_table where name=";
            ss << "'" << name << "';";
            _sql_help.exec(ss.str(), nullptr, nullptr);
        }
        // 获取所有队列
        MsgQueueMap recovery()
        {
            // create table if not exists queue_table(name varchar(32),durable,exclusive,auto_delete,args);
            // select name,durable,exclusive,auto_delete,args from queue_table;
            MsgQueueMap result;
            std::string ss = "select name,durable,exclusive,auto_delete,args from queue_table;";
            _sql_help.exec(ss, selectCallback, &result);

            return result;
        }

    private:
        static int selectCallback(void *arg, int numrow, char **res, char **fields)
        {
            MsgQueueMap *result = (MsgQueueMap *)arg;
            MsgQueue::ptr mqp = std::make_shared<MsgQueue>();
            mqp->name = res[0];
            mqp->durable = (bool)res[1];
            mqp->exclusive = (bool)res[2];
            mqp->auto_delete = (bool)res[3];
            if (res[4])
                mqp->setArgs(res[4]);

            result->insert(std::make_pair(mqp->name, mqp));
            return 0;
        }

    private:
        SqliteHelper _sql_help;
    };

    // 实现队列管理类
    class MsqQueueManagger
    {
    public:
        using ptr=std::shared_ptr<MsqQueueManagger>;
        MsqQueueManagger(const std::string &dbfile)
            : _mapper(dbfile)
        {
            _msg_queues = _mapper.recovery();
        }
        bool declareQueue(const std::string &qname,
                          bool qdurable,
                          bool qexclusive,
                          bool qauto_delete,
                          const google::protobuf::Map<std::string,std::string>& qargs)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_msg_queues.find(qname) != _msg_queues.end())
            {
                return true;
            }
            MsgQueue::ptr mqp = std::make_shared<MsgQueue>();
            mqp->name = qname;
            mqp->durable = qdurable;
            mqp->exclusive = qexclusive;
            mqp->auto_delete = qauto_delete;
            mqp->args = qargs;
            if(qdurable==true)
            {
                bool ret=_mapper.insert(mqp);
                if(ret==false)
                return false;
            }
            _msg_queues.insert(std::make_pair(qname, mqp));
            return true;
        }
        void deleteQueue(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(name);
            if (it == _msg_queues.end())
            {
                return;
            }
            if (it->second->durable == true)
            {
                _mapper.remove(name);
            }
            _msg_queues.erase(name);
        }
        MsgQueue::ptr getQueue(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(name);
            if (it == _msg_queues.end())
            {
                return MsgQueue::ptr();
            }

            return it->second;
        }
        //获取所有队列
        MsgQueueMap allQueues()
        {
            return _msg_queues;
        }
        bool isExists(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(name);
            if (it == _msg_queues.end())
            {
                return false;
            }
            return true;
        }
        size_t size()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _msg_queues.size();
        }
        void clear()
        {
            _mapper.removeTable();
            _msg_queues.clear();
        }

    private:
        std::mutex _mutex;
        MsgQueueMap _msg_queues;
        MsgQueueMapper _mapper;
    };
}
#endif